﻿using System;
using System.Collections.Generic;
using System.Linq;
using DomainModel;
using Repository.Abstract;
using Services.Abstract;
using Services.Concrete.Exceptions;

namespace Services.Concrete
{
    public class UserService : Service<User>, IUserService
    {
        private readonly IUserRepository _userRepository;

        public UserService(IUserRepository userRepository)
            : base(userRepository)
        {
            _userRepository = userRepository;
        }

        public User GetByLogin(string login)
        {
            if (login == null || string.IsNullOrEmpty(login))
                throw new ArgumentNullException("login");

            return _userRepository.GetByLogin(login);
        }

        public User GetByEmail(string email)
        {
            if (email == null || string.IsNullOrEmpty(email))
                throw new ArgumentNullException("email");

            return _userRepository.GetByEmail(email);
        }

        public List<User> Get(Role role)
        {
            return (List<User>)_userRepository.GetByRole(role);
        }

        public void Approve(User user)
        {
            if (user == null)
                throw new ArgumentNullException("user");

            if (user.IsApproved)
                return;

            user.IsApproved = true;
            Update(user);
        }

        public bool IsInRole(User user, Role role)
        {
            if (user == null)
                throw new ArgumentNullException("user");

            return user.Roles.Contains(role);
        }

        public bool IsPraepostor(User student, Group group)
        {
            if (student == null)
                throw new ArgumentNullException("student");

            if (group == null)
                throw new ArgumentNullException("group");

            if (!IsInRole(student, Role.Student))
                return false;

            return group.Praepostor == student;
        }

        public bool IsCurator(User teacher, Group group)
        {
            if (teacher == null)
                throw new ArgumentNullException("teacher");
            if (group == null)
                throw new ArgumentNullException("group");

            if (!IsInRole(teacher, Role.Teacher))
                return false;

            return group.Curator == teacher;
        }

        public bool ValidateUser(string login, string password)
        {
            if (login == null || string.IsNullOrEmpty(login))
                throw new ArgumentNullException("login");
            if (password == null || string.IsNullOrEmpty(password))
                throw new ArgumentNullException("password");

            var user = GetByLogin(login);

            return user != null && user.PasswordHash.Equals(User.GetPasswordHash(password));
        }

        public override void Save(User entity)
        {
            if (entity == null)
                throw new ArgumentNullException("entity");

            if (GetByLogin(entity.Login) != null)
                throw new CUDEntityException("User with such login already exists");

            if (GetByEmail(entity.Email) != null)
                throw new CUDEntityException("User with such email already exists");

            if (IsInRole(entity, Role.Parent))
            {
                var child = entity.Child;
                if (GetById(child.Id) == null)
                    throw new CUDEntityException("Parent's child does not exists");
            }
            else
            {
                entity.Child = null;
            }

            base.Save(entity);
        }
    }
}